<template>
  <div class="container">
    <!-- 地图容器 -->
    <div id="vue-openlayers" ref="mapContainer" class="map-container">
      <!-- 地图标题 -->
      <div class="map-title">OpenLayers 图形绘制与编辑</div>

      <!-- 左下角控制面板 -->
      <div class="control-panel bottom-left">
        <!-- 绘制按钮组 -->
        <div class="button-group">
          <button type="button" class="btn btn-success" @click="startDraw('Point')">点</button>
          <button type="button" class="btn btn-success" @click="startDraw('LineString')">线</button>
          <button type="button" class="btn btn-success" @click="startDraw('Circle')">圆</button>
          <button type="button" class="btn btn-success" @click="startDraw('Square')">正方形</button>
          <button type="button" class="btn btn-success" @click="startDraw('Rectangle')">长方形</button>
          <button type="button" class="btn btn-success" @click="startDraw('Polygon')">多边形</button>
        </div>

        <!-- 编辑按钮组 -->
        <div class="button-group">
          <button type="button" class="btn btn-primary" @click="enableModify">启用编辑</button>
          <button type="button" class="btn btn-info" @click="clearSelection">清除选择</button>
          <button type="button" class="btn btn-remove" @click="removeSelection">删除单个</button>
          <button type="button" class="btn btn-warning" @click="clearDraw">删除所有</button>
        </div>

        <!-- 样式控制面板 -->
        <div class="style-controls">
          <div class="control-group">
            <label>边框颜色：</label>
            <input type="color" v-model="strokeColor" @input="updateStyle"/>
          </div>
          <div class="control-group">
            <label>边框宽度：</label>
            <input type="range" v-model="strokeWidth" min="1" max="10" @input="updateStyle"/>
            <span>{{ strokeWidth }}px</span>
          </div>
          <div class="control-group">
            <label>填充颜色：</label>
            <input type="color" v-model="fillColor" @input="updateStyle"/>
          </div>
          <div class="control-group">
            <label>填充透明度：</label>
            <input type="range" v-model="fillOpacity" min="0" max="1" step="0.1" @input="updateStyle"/>
            <span>{{ fillOpacity }}</span>
          </div>
        </div>
      </div>
    </div>
  </div>
  <NavigationBar />
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue';
import { Map, View } from 'ol';
import TileLayer from 'ol/layer/Tile';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import WMTS from 'ol/source/WMTS';
import WMTSTileGrid from 'ol/tilegrid/WMTS';
import { get as getProjection } from 'ol/proj';
import { getTopLeft, getWidth } from 'ol/extent';
import { Draw, Modify, Snap, Select } from 'ol/interaction';
import { Style, Fill, Stroke, Circle as CircleStyle } from 'ol/style';


import Polygon from 'ol/geom/Polygon';
import Circle from 'ol/geom/Circle';
import { Point } from "ol/geom.js";
import NavigationBar from "./NavigationBar.vue";

// ========================
// 工具函数：16进制转RGBA
// ========================
const hexToRgba = (hex, opacity) => {
  const r = parseInt(hex.slice(1, 3), 16);
  const g = parseInt(hex.slice(3, 5), 16);
  const b = parseInt(hex.slice(5, 7), 16);
  return `rgba(${r}, ${g}, ${b}, ${opacity})`;
};

// ========================
// 样式创建函数
// ========================
const createStyle = () => {
  return new Style({
    fill: new Fill({
      color: hexToRgba(fillColor.value, fillOpacity.value),
    }),
    stroke: new Stroke({
      color: strokeColor.value,
      width: strokeWidth.value,
    }),
    image: new CircleStyle({
      radius: 5,
      fill: new Fill({ color: strokeColor.value }),
      stroke: new Stroke({ color: strokeColor.value, width: strokeWidth.value }),
    }),
  });
};

const createSelectStyle = () => {
  return new Style({
    stroke: new Stroke({
      color: '#ff00ff',
      width: 3,
    }),
    fill: new Fill({
      color: 'rgba(255, 0, 255, 0.3)',
    }),
  });
};

// ========================
// 响应式状态
// ========================
const mapContainer = ref(null);
const map = ref(null);

// 交互实例
const drawInteraction = ref(null);
const modifyInteraction = ref(null);
const snapInteraction = ref(null);
const selectInteraction = ref(null);

// 样式控制
const strokeColor = ref('#ece034');
const strokeWidth = ref(2);
const fillColor = ref('#ece034');
const fillOpacity = ref(0.2);

// 矢量图层和数据源
const vectorSource = ref(new VectorSource({ wrapX: false }));
const vectorLayer = ref(null);


// ========================
// 天地图 WMTS 配置
const webKey = 'e0544d1d5d87cd63d1f2d0338830974c';
const projection = getProjection('EPSG:3857');
const projectionExtent = projection.getExtent();
const size = getWidth(projectionExtent) / 256;

// 修复：创建按降序排列的分辨率数组
const resolutions = [];
for (let z = 1; z < 19; z++) {
  const resolution = size / Math.pow(2, z);
  resolutions.push(resolution);
}

const matrixIds = Array.from({ length: 18 }, (_, i) => i + 1);

const tileGrid = new WMTSTileGrid({
  origin: getTopLeft(projectionExtent),
  resolutions: resolutions, // 保持原降序顺序
  matrixIds: matrixIds,
});

const urlVec = `http://t0.tianditu.gov.cn/vec_c/wmts?tk=${webKey}`;
const urlCva = `http://t0.tianditu.gov.cn/cva_c/wmts?tk=${webKey}`;

const vecLayer = new TileLayer({
  source: new WMTS({
    url: urlVec,
    layer: 'vec',
    matrixSet: 'c',
    format: 'tiles',
    style: 'default',
    projection: projection,
    tileGrid: tileGrid,
    wrapX: true,
  }),
});

const cvaLayer = new TileLayer({
  source: new WMTS({
    url: urlCva,
    layer: 'cva',
    matrixSet: 'c',
    format: 'tiles',
    style: 'default',
    projection: projection,
    tileGrid: tileGrid,
    wrapX: false,
  }),
});

// ========================
// 移除所有交互
// ========================
const removeInteractions = () => {
  const interactions = [
    drawInteraction,
    modifyInteraction,
    selectInteraction,
    snapInteraction,
  ];
  interactions.forEach((interactionRef) => {
    if (interactionRef.value && map.value) {
      map.value.removeInteraction(interactionRef.value);
      interactionRef.value = null;
    }
  });
};

// ========================
// 开始绘制
// ========================
const startDraw = (type) => {
  removeInteractions();

  let geometryFunction;
  let typeToDraw = type;

  // 在 startDraw 函数中找到 Square 类型的处理部分并修改为以下代码：
  if (type === 'Square') {
    typeToDraw = 'LineString';
    geometryFunction = (coordinates, geometry) => {
      if (coordinates.length < 2) {
        return new Point(coordinates[0]);
      }

      const center = coordinates[0];
      const corner = coordinates[1];
      const dx = corner[0] - center[0];
      const dy = corner[1] - center[1];

      const squareCoords = [
        [center[0] + dx, center[1] + dy],
        [center[0] - dy, center[1] + dx],
        [center[0] - dx, center[1] - dy],
        [center[0] + dy, center[1] - dx],
        [center[0] + dx, center[1] + dy]
      ];

      if (!geometry) {
        geometry = new Polygon([squareCoords]);
      } else {
        geometry.setCoordinates([squareCoords]);
      }
      return geometry;
    };

    drawInteraction.value = new Draw({
      source: vectorSource.value,
      type: typeToDraw,
      style: createStyle(),
      geometryFunction: geometryFunction,
    });

    // 👇 关键：在绘制结束时，强制替换为标准 Polygon 几何
    drawInteraction.value.on('drawend', (event) => {
      const feature = event.feature;
      const tempGeom = feature.getGeometry();

      // 提取当前已生成的坐标（即 preview polygon）
      const polyCoords = tempGeom.getCoordinates();

      // 创建独立的新 Polygon
      const finalPolygon = new Polygon(polyCoords);
      feature.setGeometry(finalPolygon); // 替换掉原来的"伪多边形"
    });

    // 添加交互到地图
    map.value.addInteraction(drawInteraction.value);

    snapInteraction.value = new Snap({ source: vectorSource.value });
    map.value.addInteraction(snapInteraction.value);
    return;
  } else if (type === 'Rectangle') {
    typeToDraw = 'LineString';
    geometryFunction = function (coordinates, geometry) {
      if (coordinates.length < 2) return geometry;

      const start = coordinates[0];
      const end = coordinates[1];

      const minX = Math.min(start[0], end[0]);
      const minY = Math.min(start[1], end[1]);
      const maxX = Math.max(start[0], end[0]);
      const maxY = Math.max(start[1], end[1]);

      const rectCoords = [
        [minX, minY],
        [maxX, minY],
        [maxX, maxY],
        [minX, maxY],
        [minX, minY] // 闭合
      ];

      if (!geometry) {
        geometry = new Polygon([rectCoords]);
      } else {
        geometry.setCoordinates([rectCoords]);
      }
      return geometry;
    };
  }

  drawInteraction.value = new Draw({
    source: vectorSource.value,
    type: typeToDraw,
    style: createStyle(),
    geometryFunction: geometryFunction,
    maxPoints: type === 'Rectangle' ? 2 : undefined,
  });

  map.value.addInteraction(drawInteraction.value);

  snapInteraction.value = new Snap({ source: vectorSource.value });
  map.value.addInteraction(snapInteraction.value);

  // 绘制结束后自动进入编辑模式
  drawInteraction.value.on('drawend', () => {
    enableModify();
  });
};

// ========================
// 启用编辑模式（Modify + Select + Snap）
// ========================
const enableModify = () => {
  if (!vectorLayer.value || !map.value) return;

  removeInteractions(); // 先清除旧的交互

  // 创建 Select 交互，限定图层
  selectInteraction.value = new Select({
    layers: [vectorLayer.value],
    style: createSelectStyle(),
  });

  // 创建 Modify 交互，传入当前选中的要素（可能为空）
  modifyInteraction.value = new Modify({
    features: selectInteraction.value.getFeatures(), // 初始为空
  });

  selectInteraction.value.on('select', (evt) => {
    console.log('选中了要素：', evt.selected.length, '个');
  });

  const allFeatures = vectorSource.value.getFeatures();
  selectInteraction.value.getFeatures().extend(allFeatures); // 直接选中所有要素！

  // 添加交互到地图
  map.value.addInteraction(selectInteraction.value);
  map.value.addInteraction(modifyInteraction.value);

  // Snap 交互
  snapInteraction.value = new Snap({ source: vectorSource.value });
  map.value.addInteraction(snapInteraction.value);

  console.log(`[enableModify] 当前地图中有 ${allFeatures.length} 个要素，已全部选中并启用编辑。`);
};

// ========================
// 清除选择
// ========================
const clearSelection = () => {
  if (selectInteraction.value) {
    selectInteraction.value.getFeatures().clear();
  }
};


// ========================
// 删除所选择的图形
// ========================
const removeSelection = () => {
  if (selectInteraction.value) {
    const selectedFeatures = selectInteraction.value.getFeatures();
    // 清除选中状态
    selectedFeatures.forEach(feature => {
      vectorSource.value.removeFeature(feature);
    });
    // 清空选中的要素集合
    selectedFeatures.clear();
  }
};

// ========================
// 清除所有图形
// ========================
const clearDraw = () => {
  vectorSource.value.clear();
  clearSelection();
};

// ========================
// 更新样式（实时）
// ========================
const updateStyle = () => {
  const style = createStyle();

  // 更新图层样式
  if (vectorLayer.value) {
    vectorLayer.value.setStyle(style);
  }

  // 更新所有已有要素的样式
  if (vectorSource.value) {
    vectorSource.value.forEachFeature((feature) => {
      feature.setStyle(style);
    });
  }

  // 更新绘制交互样式
  if (drawInteraction.value) {
    drawInteraction.value.setStyle(style);
  }
};


// ========================
// 初始化地图
// ========================
onMounted(async () => {
  await nextTick(); // 确保 DOM 已渲染

  if (!mapContainer.value) {
    console.error('【DrawGraph】地图容器 #vue-openlayers 未找到！');
    return;
  }

  try {
    // 创建矢量图层
    vectorLayer.value = new VectorLayer({
      source: vectorSource.value,
      style: createStyle(),
    });

    // 初始化地图
    map.value = new Map({
      target: mapContainer.value,
      layers: [vecLayer, cvaLayer, vectorLayer.value],
      view: new View({
        center: [0, 0],
        zoom: 2,
        minZoom: 2,
        maxZoom: 18,
      }),
    });

    // 启用编辑模式（依赖 vectorLayer）
    enableModify();
  } catch (error) {
    console.error('【DrawGraph】地图初始化失败：', error);
  }
});

// ========================
// 组件卸载前清理地图
// ========================
onBeforeUnmount(() => {
  if (map.value) {
    map.value.setTarget(undefined); // 解绑 DOM
    map.value = null;
  }
  removeInteractions();
});
</script>

<style scoped>
.container {
  width: 100vw;
  height: 100vh;
  margin: 0;
  padding: 0;
}

.map-container {
  width: 100%;
  height: 100%;
  position: relative;
}

.map-title {
  position: absolute;
  top: 10px;
  left: 0;
  right: 0;
  text-align: center;
  z-index: 1000;
  font-size: 18px;
  font-weight: bold;
  color: #333;
  background: rgba(255, 255, 255, 0.7);
  padding: 8px 16px;
  border-radius: 4px;
  margin: 0 auto;
  width: fit-content;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.control-panel.bottom-left {
  position: absolute;
  bottom: 20px;
  left: 20px;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.button-group {
  display: flex;
  gap: 8px;
  padding: 8px;
  background: rgba(255, 255, 255, 0.7);
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.btn {
  padding: 6px 12px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
}

.btn-success {
  background-color: #67c23a;
  color: white;
}

.btn-warning {
  background-color: #f56c6c;
  color: white;
}

.btn-primary {
  background-color: #409eff;
  color: white;
}

.btn-info {
  background-color: #909399;
  color: white;
}

.btn-remove {
  background-color: #f56c6c;
  color: white;
}

.style-controls {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px;
  background: rgba(255, 255, 255, 0.8);
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.control-group {
  display: flex;
  align-items: center;
  gap: 8px;
}

.control-group label {
  font-size: 12px;
  white-space: nowrap;
  min-width: 70px;
}

.control-group input[type='range'] {
  width: 80px;
}

.control-group span {
  min-width: 30px;
  text-align: right;
}
</style>

<style>
/* 全局样式：OpenLayers 选中高亮动画 */
.ol-selected {
  animation: pulse 1s infinite;
}

@keyframes pulse {
  0% {
    opacity: 0.8;
  }
  50% {
    opacity: 1;
  }
  100% {
    opacity: 0.8;
  }
}
</style>